package com.myk.game.gobangchess.rooms.oldrooms;

import com.myk.game.gobangchess.*;
import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.rooms.absrooms.AbsChessRoom;
import com.myk.game.gobangchess.signs.ColorSign;
import com.myk.game.gobangchess.signs.FigureSign;
import com.myk.game.gobangchess.signs.GroundSign;
import com.myk.game.gobangchess.signs.TextSign;
import com.myk.game.gobangchess.utils.GridsUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 我原创的棋类游戏 《盗公骑冠剑》
 */
public class PrincessKnightCrownSwordRoom extends AbsChessRoom {

    private List<Sign> chessboardStyle; //不变的棋盘样式
    private int[][] chessGrids; //用于方便逻辑运算得棋子棋盘
    private List<Chess> chessList; //场上棋子集合
    private Chess choose; //当前选中的棋子
    private boolean gameOverFlag;

    public PrincessKnightCrownSwordRoom(String roomName) {
        super(roomName, "\t\t\t\t江柯设计的杀王棋。驱动棋子，抢夺神冠与圣剑，击杀对方公主。\n\t\t\t\t(目前处于测试阶段没有实现逻辑)", "盗公骑冠剑", BoardStyleData.getGoBangStyle(7, 5), true, false);
        initChessBoardStyle();
    }

    public void initChessBoardStyle() {
        int row = curGrids.length;
        int col = curGrids[0].length;
        chessboardStyle = new ArrayList<>();
        //绘制类似国际象棋的黑白相间的格子
        List<Integer> bGrids = new ArrayList<>();
        List<Integer> wGrids = new ArrayList<>();
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                int index = getIndex(i, j);
                if ((i + j) % 2 == 0) {
                    bGrids.add(index);
                }
                else {
                    wGrids.add(index);
                }
            }
        }
        chessboardStyle.add(new ColorSign(bGrids, "#FF888888"));
        chessboardStyle.add(new ColorSign(wGrids, "#FFDDDDDD"));
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(curGrids.length - 1, curGrids[0].length - 1), "#00000000", "#FF333333", 1.8f, 0, 0));
    }

    @Override
    protected void doStart() {
        DataManager.noticeAllGameStart(player_black, player_white, roomName);
        overFlag = 1;//重置结束状态：对弈进行中未结束
        playingStartTime = System.currentTimeMillis(); //重置对弈开始时间
        resetGrids(); //先清空棋盘信息
        initChessList();//游戏开始的时候初始化棋子和布局
        noticeBlackMove();
        preHistory(); //准备记录日志
    }

    @Override
    public void resetGrids() {
        step = 0;
        gameTip = "-1";
        signList.clear();
        chessList = null;
        choose = null;
        gameOverFlag = false;
    }

    @Override
    public void noticeBlackMove() {
        super.noticeBlackMove();
        blackBottom();
    }

    @Override
    public void noticeWhiteMove() {
        super.noticeWhiteMove();
        whiteBottom();
    }

    @Override
    public void noticeOnSeatReConnectMove(Player player) {
        super.noticeOnSeatReConnectMove(player);
        if (cur == 1){
            blackBottom();
        }
        else if (cur == 2){
            whiteBottom();
        }
    }

    private void blackBottom() {
        if (player_black != null) {
            player_black.registerCustomBottom(new CustomBottom(this, "结束行动", player -> {
                player.clearCustomBottom();
                player.dispatchCustomBottom();
                noticeWhiteMove();
            }));
        }
    }

    private void whiteBottom() {
        if (player_white != null){
            player_white.registerCustomBottom(new CustomBottom(this, "结束行动", player -> {
                player.clearCustomBottom();
                player.dispatchCustomBottom();
                noticeBlackMove();
            }));
        }
    }

    @Override
    public String getRuleText() {
        return null;
    }

    @Override
    public String getGameInfo() {
        //先全部初始化
        signList.clear();
        //绘制背景
        signList.addAll(chessboardStyle);
        //根据chessList集合和choose对象来生成要显示到客户端的布局和标记
        if (chessList != null && chessList.size() > 0) {
            for (Chess chess : chessList) {
                if (chess.isShow) {
                    signList.addAll(chess.appearance); //显示棋子的外观
                }
            }
            if (choose != null && choose.isShow) { //棋子被选中状态时
                signList.add(FigureSign.makeSingleFigure(getIndex(choose.pRow, choose.pCol), choose.getNameColor()).setAdjMidLine(1, 1, 1, 1)); //聚焦格子
                List<int[]> canMovedPosList = choose.getCanMovedPos(); //获取该棋子可移动到的格子的坐标集合
                if (canMovedPosList != null && canMovedPosList.size() > 0) {
                    for (int[] canMovedPos : canMovedPosList) {
                        int index = getIndex(canMovedPos[0], canMovedPos[1]);
                        signList.add(new TextSign(index, "⊙", "#AA33FF33")); //可移动到的格子用更淡的绿色表示
                    }
                }
            }
        }
        return super.getGameInfo();
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (choose == null) { //如果目前没有选中的单位
            Chess chess = getChessByPos(row, col);
            if (chess != null) { //选中得是己方棋子或者中立棋子时
                choose = chess; //选中己方棋子
                noticeAllRefreshGameInfo(); //仅仅刷新显示，还能继续点击
            }
        }
        else { //如果已经有选中的单位
            if (choose.isPosCanMove(row, col)) { //点击的位置属于选中棋子的可移动范围
                choose.doMove(row, col);
                stepAdd();;
                choose = null;
                if (isGameOver()) {
                    if (value == 1) {
                        doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "获胜！");
                    }
                    else {
                        doOver(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "获胜！");
                    }
                }
                else {
                    noticeAllRefreshGameInfo();
                }
            }
            else { //点击了不可移动的位置时
                choose = null; //点击了其它地方则关闭可移动路径的标记
                noticeAllRefreshGameInfo(); //仅仅刷新显示，黑方还能继续点击
            }
        }
    }


    private void initChessList() {
        chessGrids = GridsUtils.copyGrids(originGrids);
        chessList = new ArrayList<>();
        chessList.add(new Robber(1, 0, 0, this));
        chessList.add(new Knight(1, 0, 1, this));
        chessList.add(new Princess(1, 0, 2, this));
        chessList.add(new Knight(1, 0, 3, this));
        chessList.add(new Robber(1, 0, 4, this));
        chessList.add(new Crown(7, 3, 1, this));
        chessList.add(new Sword(7, 3, 3, this));
        chessList.add(new Robber(2, 6, 0, this));
        chessList.add(new Knight(2, 6, 1, this));
        chessList.add(new Princess(2, 6, 2, this));
        chessList.add(new Knight(2, 6, 3, this));
        chessList.add(new Robber(2, 6, 4, this));
    }

    private Chess getChessByPos(int row, int col) {
        for (Chess chess : chessList) {
            if (chess.isShow && chess.pRow == row && chess.pCol == col) {
                return chess;
            }
        }
        return null;
    }

    private boolean isGameOver() {
        return gameOverFlag;
    }


    private abstract static class Chess {
        PrincessKnightCrownSwordRoom room; //上下文环境
        String mName; //棋子简名
        int mSide; //归属黑棋还是白棋
        int pRow; //在棋盘上的横坐标
        int pCol; //在棋盘上的纵坐标
        boolean isShow; //棋子是否显示？
        List<Sign> appearance;//棋子的外观，自定义标记组合而成的外观

        public Chess(String mName, int mSide, int pRow, int pCol, PrincessKnightCrownSwordRoom room) {
            this.room = room;
            this.mName = mName;
            this.mSide = mSide;
            this.pRow = pRow;
            this.pCol = pCol;
            this.isShow = true;
            this.appearance = new ArrayList<>();
            room.chessGrids[pRow][pCol] = mSide;
            setAppearance();
        }

        //获取可移动范围列表
        public List<int[]> getCanMovedPos() {
            List<int[]> canMovedPosList = new ArrayList<>();
            int h = room.chessGrids.length;
            int w = room.chessGrids[0].length;
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    if (isPosCanMove(i, j)) {
                        canMovedPosList.add(new int[]{i, j});
                    }
                }
            }
            return canMovedPosList;
        }

        //个性化的移动算法
        public abstract boolean isPosCanMove(int row, int col);

        //设置棋子的外观
        public abstract void setAppearance();

        public abstract String getRecordName();


        protected String getNameColor() {
            if (mSide == 1) {
                return "#FFFF0000";
            }
            else if (mSide == 2) {
                return "#FF0000FF";
            }
            else if (mSide == 7) {
                return "#FFFFFF00";
            }
            else {
                return null;
            }
        }

        protected String getBorderColor() {
            if (mSide == 1) {
                return "#FF000000";
            }
            else if (mSide == 2) {
                return "#FFFFFFFF";
            }
            else if (mSide == 7) {
                return "#FFFFFF00";
            }
            else {
                return null;
            }
        }

        public void doMove(int row, int col) {
            Chess hasChess = room.getChessByPos(row, col);
            if (hasChess != null) {
                hasChess.doDie();
            }
            room.chessGrids[pRow][pCol] = 0;
            room.chessGrids[row][col] = mSide;
            this.pRow = row;
            this.pCol = col;
            setAppearance(); //更新图像
        }

        public void doDie() {
            this.isShow = false;
            room.chessGrids[pRow][pCol] = 0;
        }
    }

    private static class Princess extends Chess {

        public Princess(int mSide, int pRow, int pCol, PrincessKnightCrownSwordRoom room) {
            super("公主", mSide, pRow, pCol, room);
        }


        @Override
        public boolean isPosCanMove(int row, int col) {
            return room.getChessByPos(row, col) != this;
        }

        @Override
        public void setAppearance() {
            appearance.clear();
            appearance.add(new TextSign(room.getIndex(pRow, pCol), getRecordName(), getNameColor()));
        }

        @Override
        public String getRecordName() {
            return mSide == 1 ? "公" : "主";
        }

        @Override
        public void doDie() {
            super.doDie();
            room.gameOverFlag = true;
        }
    }

    private static class Knight extends Chess {

        public Knight(int mSide, int pRow, int pCol, PrincessKnightCrownSwordRoom room) {
            super("骑兵", mSide, pRow, pCol, room);
        }

        @Override
        public boolean isPosCanMove(int row, int col) {
            return room.getChessByPos(row, col) != this;
        }

        @Override
        public void setAppearance() {
            appearance.clear();
            appearance.add(new TextSign(room.getIndex(pRow, pCol), getRecordName(), getNameColor()));
        }

        @Override
        public String getRecordName() {
            return mSide == 1 ? "骑" : "兵";
        }
    }

    private static class Robber extends Chess {

        public Robber(int mSide, int pRow, int pCol, PrincessKnightCrownSwordRoom room) {
            super("盗贼", mSide, pRow, pCol, room);
        }


        @Override
        public boolean isPosCanMove(int row, int col) {
            return room.getChessByPos(row, col) != this;
        }

        @Override
        public void setAppearance() {
            appearance.clear();
            appearance.add(new TextSign(room.getIndex(pRow, pCol), getRecordName(), getNameColor()));
        }

        @Override
        public String getRecordName() {
            return mSide == 1 ? "盗" : "贼";
        }
    }

    private static class Crown extends Chess {


        public Crown(int mSide, int pRow, int pCol, PrincessKnightCrownSwordRoom room) {
            super("神冠", mSide, pRow, pCol, room);
        }


        @Override
        public boolean isPosCanMove(int row, int col) {
            return room.chessGrids[row][col] == 0;
        }

        @Override
        public void setAppearance() {
            appearance.clear();
            appearance.add(FigureSign.makeSingleFigure(room.getIndex(pRow, pCol), getBorderColor()).setAdjMidLine(1, 1, 1, 1)); //聚焦格子
            appearance.add(new TextSign(room.getIndex(pRow, pCol), getRecordName(), getNameColor()));
        }

        @Override
        public String getRecordName() {
            return "冠";
        }
    }

    private static class Sword extends Chess {

        public Sword(int mSide, int pRow, int pCol, PrincessKnightCrownSwordRoom room) {
            super("圣剑", mSide, pRow, pCol, room);
        }

        @Override
        public boolean isPosCanMove(int row, int col) {
            return room.chessGrids[row][col] == 0;
        }

        @Override
        public void setAppearance() {
            appearance.clear();
            appearance.add(FigureSign.makeSingleFigure(room.getIndex(pRow, pCol), getBorderColor()).setAdjMidLine(1, 1, 1, 1)); //聚焦格子
            appearance.add(new TextSign(room.getIndex(pRow, pCol), getRecordName(), getNameColor()));
        }

        @Override
        public String getRecordName() {
            return "剑";
        }
    }
}
